# -*- coding: utf-8 -*-
VERSION = '0.9.0'

import sys
import os
import gobject

import shutil

import Plugin


from threading import Thread
#import time

#import aspects
from Wrappers import *


import KiduxConfig
# Must Have, to append a new .py lib to the python engine. All Kidux .py :)
KiduxConfig.KiduxConfig().fixSystemPath()

from KiduxGladeDialog import *
from KiduxParentalController import *
from Auxiliary import *

class MainClass(Plugin.Plugin):
    description = _('Kidux Parental Control')
    authors = { 'Rd' : 'rfatao@gmail.com',
                'Tiago' : 'tndreyer@uol.com.br'}
    website = "www.kidux.net"
    displayName = 'Kidux Parental Control'
    name = "KiduxPAC"

    def __init__(self, controller, msn):
        Plugin.Plugin.__init__(self, controller, msn)
        self.description = _('Kidux Parental Control')
        self.authors = { 'Rd' : 'rfatao@gmail.com',
                         'Tiago' : 'tndreyer@uol.com.br'}
        self.website = "www.kidux.net"
        self.displayName = 'Kidux Parental Control'
        self.name = "KiduxPAC"

        self.controller = controller
        
        self.msn = msn
        self.accountUser = msn.user
        self.personalIP = msn.socket._host
        
        self.mainKiduxDebug = True
        self.debugCount = 0
	self.boolInfo = True
	self.quarentineDir = os.path.expanduser('~')+"/quarentine/" # still using the ~/quarentine/
	self.switchboardList = []


    def start(self):
        print "Kidux Parental Control Enabled"
	self.wrappers = Wrappers(self)
        self.buddyList = self.controller.contacts.contacts.keys()
        dictGroup = self.controller.groups.groups
        
        self.parentalController = KiduxParentalController(self, self.accountUser, True)
        self.parentalController.start()
        self.dialogs = KiduxGladeDialog()

        self.wrappers.addWrappers()
        self.checkAccountBlockedAndCreate(self.accountUser, self.buddyList, dictGroup)

        #self.filterList(BlockContact(self.controller))

        #TODO: Everyone still offline on the very start, so, lauch a thread and wait 10 seconds
        self.infoSender = InitialInfoSender(self, self.buddyList)
	self.infoSender.setDaemon(True)
        self.infoSender.start()
        self.enabled = True

    def stop(self):
        self.shuttingDown()
        self.parentalController.stop()
        self.wrappers.removeWrappers()
        self.enabled = False
        print "Kidux Parental Control Disabled"

    def check(self):
        print "check"
        return (True, 'Ok')


    def initializer():
	return (True, 'Ok')

#####################################
    def __kiduxPluginDebug(self, msg):
	if self.mainKiduxDebug:
	    print "****************************************"
	    print "KIDUX-PLUGIN DEBUG"
	    print self.debugCount, msg
	    self.debugCount += 1
	    print "****************************************"

    def shuttingDown(self):
        self.__kiduxPluginDebug("shuttingDown")
        offlineList = self.buddyList
        self.parentalController.disconnect(self.accountUser)

    def getEntireBuddyListDict(self, buddyList,  dictGroups):
        self.__kiduxPluginDebug("getEntireBuddyListDict")
        dictLenght = len(dictGroups)
        dictKeys = dictGroups.keys()
        dictGroupByBuddies = {}
        count = 0
        while dictKeys:
            # No function to wrap that just return us a group name, given the contact...
            if count >= dictLenght:
                break
            groupName = dictKeys[count]
            #if len(dictContacts) != 0:
            dictGroupByBuddies[groupName] = dictGroups[groupName].contacts
                #for contactId in dictContacts:
                #dictGroupByBuddies[contactId] = groupName
            count += 1
        return dictGroupByBuddies
#####################################

    def userUnblocked(self, *args, **kwargs):
        self.__kiduxPluginDebug("userUnblocked")
        contactId = args[1]
        self.aspectsCallBack(contactId, *args, **kwargs)

    def userBlocked(self, *args, **kwargs):
        self.__kiduxPluginDebug("userBlocked")
        contactId = args[1]

        ret = self.isContactAllowed(contactId)
        if not ret:
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)

    def preventPluginUnloading(self, *args, **kwargs):
        self.__kiduxPluginDebug("preventPluginUnloading")
        path = args[2]
        model, column = args[3]
        iterator= model.get_iter_from_string(path)
        pluginName = model.get_value(iterator, 2) # Plugin Display Name
        if not pluginName == self.displayName: # Kidux Parental Controller
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)

    def addingContact(self, *args,  **kwargs):
        self.__kiduxPluginDebug("addingContact")
        contactId = args[1]
        group = args[2]
        if not contactId in self.buddyList:
            self.buddyList.append(contactId)
        self.parentalController.addContact(self.accountUser, contactId, group)
        retval = yield aspects.proceed(*args,  **kwargs)
        yield aspects.return_stop(retval)

    def userJoin(self, *args,  **kwargs):
	self.__kiduxPluginDebug("userJoin")
	contacts = args[1].members.keys()
	contactId = args[2]
	conversationId = args[1].authenticationString
	print "userJoin" , "conversationId: " , conversationId
	sizeContacts = len(contacts)
	if sizeContacts == 1:
	    if not conversationId in self.switchboardList:
		self.parentalController.startConversation(self.accountUser, conversationId, contacts)
		self.switchboardList.append(conversationId)
	elif sizeContacts > 1:
	    self.parentalController.enterConversation(self.accountUser, conversationId, contactId)
	else:
	    pass
	    
	retval = yield aspects.proceed(*args,  **kwargs)
        yield aspects.return_stop(retval)

    def userLeave(self, *args,  **kwargs):
	self.__kiduxPluginDebug("userLeave")
	members = args[1].members.keys()
	contactId = args[2]
	conversationId = args[1].authenticationString
	sizeMembers = len(members)
	#if sizeMembers > 1:
	self.parentalController.leaveConversation(self.accountUser, conversationId, contactId)
	#elif sizeMembers == 1:
	    #TODO: create the RemoveConversation
	    #raise NotImplementedError
	retval = yield aspects.proceed(*args,  **kwargs)
        yield aspects.return_stop(retval)

    def filterConversation(self, *args, **kwargs):
        self.__kiduxPluginDebug("filterConversation")
        contactId = args[2]
        isOutgoing = args[4]
        contactIP = args[1].socket._host
	switchboard = args[3]
	if switchboard:
	    contacts = switchboard.members.keys()
	    if not len(contacts) > 1:
		receiver = switchboard.firstUser
		conversationId = switchboard.authenticationString
		print "filterConversation" , "conversationId: " , conversationId
		if not conversationId in self.switchboardList:
		    self.parentalController.startConversation(self.accountUser, conversationId, contacts)
		    self.switchboardList.append(conversationId)
	else:
	    pass
        ret = self.isContactAllowed(contactId)
        if ret:
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)
        if isOutgoing == False:
            if args[3] != None:
                receiverIP = args[3].host
                sender = args[3].firstUser
                senderIP = self.personalIP
                receiver = self.accountUser
		conversationId = args[3].authenticationString
		print "filterConversation" , "conversationId: " , conversationId
		self.parentalController.logConversation(self.accountUser, conversationId, contactId, "[Blocked Window]")
        else:
            self.dialogs.showConversationBlockedDialog(contactId)

    def preventBlock(self, *args, **kwargs):
        self.__kiduxPluginDebug("preventBlock")
        contactId = args[1]
        ret = self.isContactAllowed(contactId)
        if not ret:
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)
        else:
            pass
            #self.dialogs.unblockPreventDialog(contactId)

    def preventUnblock(self, *args, **kwargs):
        self.__kiduxPluginDebug("preventUnblock")
        contactId = args[1]
        ret = self.isContactAllowed(contactId)
        if ret:
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)
        else:
            #self.dialogs.unblockPreventDialog(contactId)
            pass

    def passportPuid(self, *args, **kwargs):
        self.__kiduxPluginDebug("passportPuid")
        status = args[2]
        if status == "HDN":
            status = False
        else:
            status = True
        self.parentalController.setStatus(self.accountUser, None, status)
        retval = yield aspects.proceed(*args,  **kwargs)
        yield aspects.return_stop(retval)

    def personalStatusChanged(self, *args, **kwargs):
        self.__kiduxPluginDebug("personalStatusChanged")
        status = args[2]
        if status == "HDN":
            status = False
        else:
            status = True
        self.parentalController.setStatus(self.accountUser, None, status)
        retval = yield aspects.proceed(*args,  **kwargs)
        yield aspects.return_stop(retval)

    def personalNickChanged(self, *args, **kwargs):
        self.__kiduxPluginDebug("personalNickChanged")
        contactId = None
        nickName = args[0].tNick.get_text()
        #TODO: descomentar isso quando unicorn estiver OK...
        self.parentalController.setNickName(self.accountUser, contactId, nickName)
        retval = yield aspects.proceed(*args,  **kwargs)
        yield aspects.return_stop(retval)

    def personalMessageChanging(self, *args, **kwargs):
        self.__kiduxPluginDebug("personalMessageChanging")
        contactId = None
        personalMessage = args[0].personalMessage
        #TODO: descomentar isso quando unicorn estiver OK...
        self.parentalController.setPersonalMessage(self.accountUser, contactId, personalMessage)
        retval = yield aspects.proceed(*args,  **kwargs)
        yield aspects.return_stop(retval)

    def personalAvatarChanging(self, *args, **kwargs):
        self.__kiduxPluginDebug("personalAvatarChanging")
        contactId = None
        imagePath = args[1]
        #avatar64 = self.avatarFileToBase64(imagePath)
        #TODO: descomentar isso quando unicorn estiver OK...
        self.parentalController.setAvatar(self.accountUser, contactId, imagePath)
        retval = yield aspects.proceed(*args,  **kwargs)
        yield aspects.return_stop(retval)

    #TODO this function is only for external nick change, not for the local user
    def contactNickChanged(self, *args, **kwargs):
        self.__kiduxPluginDebug("contactNickChanged")
        contactId = args[1]
        nickName = args[2]
	if not self.boolInfo:
	    self.parentalController.setNickName(self.accountUser, contactId, nickName)
	else:
	    self.infoSender.setNickName(contactId, nickName)
        ret = self.isContactAllowed(contactId)
        if ret:
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)
        else:
            pass

    #TODO this function is only for the LOCAL USER, find the best WRAP
    def localContactNickChanged(self, *args, **kwargs):
        self.__kiduxPluginDebug("localContactNickChanged")
        contactId = args[1]
        nickName = args[2]
        self.parentalController.setNickName(self.accountUser, contactId, nickName)
        ret = self.isContactAllowed(contactId)
        if ret:
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)
        else:
            self.dialogs.setAliasPreventDialog(contactId)

    def contactPersonalMessage(self, *args, **kwargs):
        self.__kiduxPluginDebug("contactPersonalMessage")
        contactId = args[1]
        message = args[2]
	if not self.boolInfo:
	    self.parentalController.setPersonalMessage(self.accountUser, contactId, message)
	else:
	    self.infoSender.setPersonalMessage(contactId, message)
        ret = self.isContactAllowed(contactId)
        if ret:
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)
        else:
            kiduxArgs = args[0], args[1], "[Blocked] "+contactId
            retval = yield aspects.proceed(*kiduxArgs,  **kwargs)
            yield aspects.return_stop(retval)

    def contactStatusChanging(self, *args, **kwargs):
        self.__kiduxPluginDebug("contactStatusChanging")
        contactId = args[1]
        status = args[2]
        if status == 'FLN' or status == 0:
            isOnline = False
        else:
            isOnline = True
        self.parentalController.setStatus(self.accountUser, contactId, isOnline)
        retval = yield aspects.proceed(*args,  **kwargs)
        yield aspects.return_stop(retval)

    def contactNewGroup(self, *args, **kwargs):
        self.__kiduxPluginDebug("contactNewGroup")
        contactId = args[1]
        oldName = args[2]
        newName = args[3]
        self.parentalController.setGroup(self.accountUser, contactId, newName)
        retval = yield aspects.proceed(*args,  **kwargs)
        yield aspects.return_stop(retval)

    def contactBeeingRemoved(self, *args, **kwargs):
        self.__kiduxPluginDebug("contactBeeingRemoved")
        contactId = args[1]
        #TODO: descomentar
        #self.parentalController.setContactRemove(self.accountUser, contactId)
        retval = yield aspects.proceed(*args,  **kwargs)
        yield aspects.return_stop(retval)

    def contactInitialStatus(self, *args, **kwargs):
        self.__kiduxPluginDebug("contactInitialStatus")
        retval = yield aspects.proceed(*args,  **kwargs)
        yield aspects.return_stop(retval)

    def contactNewAvatarChanging(self, *args, **kwargs):
        self.__kiduxPluginDebug("contactNewAvatarChanging")
        contactId = args[4]
        contact = self.controller.getContact(contactId)
        imageName = contact.displayPicturePath
        imageCachePath = self.controller.config.getCachePath()            
        imagePath = imageCachePath+"/"+imageName
        self.parentalController.setAvatar(self.accountUser,  contactId,  imagePath)
        retval = yield aspects.proceed(*args,  **kwargs)
        yield aspects.return_stop(retval)

    def setUserPicture(self, *args, **kwargs):
        self.__kiduxPluginDebug("setUserPicture")
        contactId = args[1]._email
        if self.isContactAllowed(contactId):
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)
        else:
            pix = self.dialogs.getPix()
            yield aspects.return_stop(pix)

    def filterList(self, functor):
        self.__kiduxPluginDebug("filterList")
        for contact in self.buddyList:
            if not self.isContactAllowed(contact):
                functor(contact)

    def fileTransfer(self,  *args,  **kwargs):
        self.__kiduxPluginDebug("fileTransfer")
        sender = args[1].mail
        if self.isFileTransferAllowed(sender):
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)
        else :
            self.dialogs.fileTransferPreventDialog(sender)

    def fileSend(self,  *args,  **kwargs):
        self.__kiduxPluginDebug("fileSend")
        receiver = args[0].parentUI.parentConversation.switchboard.firstUser
        if self.isFileTransferAllowed(receiver):
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)
        else :
            self.dialogs.fileTransferPreventDialog(receiver)

    def fileReceived(self,  *args,  **kwargs):
        self.__kiduxPluginDebug("fileReceived")
	fileName = args[3].filename
	sender = args[5]
	receiver = args[1].mail
	filePath = self.__fileReceivedFinder(args[0], sender)
	switchboard = args[0].conversation.switchboard
	conversationId = switchboard.authenticationString
	print "fileReceived" , "conversationId: " , conversationId
	if sender == 'Me':
	    sender = self.accountUser
	    contactId = None
	else:
	    contactId = sender

        retval = yield aspects.proceed(*args,  **kwargs)
	#filePath = self.__fileReceivedRelocation(filePath, fileName)
	self.parentalController.logFileTransfer(self.accountUser, contactId, conversationId, filePath)
        yield aspects.return_stop(retval)

    def __fileReceivedRelocation(self, userFilePath, fileName):
	#if not os.path.exists(self.quarentineDir):
	    #os.mkdir(self.quarentineDir)
	#TODO: ticket #429
	#if os.path.exists(self.quarentineDir+fileName):
	    #os.remove(self.quarentineDir+fileName)
	quarentineFile = self.quarentineDir
	shutil.move(userFilePath, quarentineFile)
	quarentinePath = quarentineFile+fileName
	os.symlink(quarentinePath, userFilePath)
	return quarentinePath

    def __fileReceivedFinder(self, classObject, sender):
	config = classObject.controller.config
	receivedFilesDir = os.path.expanduser(config.user['receivedFilesDir'])
	# if directory is invalid, save to home directory
	if not os.path.exists(receivedFilesDir):
	    receivedFilesDir = os.path.expanduser('~/')
	# separated folders between contacts
	if config.user['receivedFilesSortedByUser']:
	    receivedFilesDirSub = os.path.join(receivedFilesDir, sender)

	    if os.path.exists(receivedFilesDirSub):
		receivedFilesDir = receivedFilesDirSub
	    else:
		os.mkdir(receivedFilesDirSub)
		# ugly, but "if os.mkdir(..)" doesn't work :S
		if os.path.exists(receivedFilesDirSub):
		    receivedFilesDir = receivedFilesDirSub
		    # if we can't create the dir, we put the file directly
		    # in received files dir
	dirPath = receivedFilesDir
	name = os.path.join(receivedFilesDir, classObject.context.filename)
	return name

    def menuFileSend(self,  *args,  **kwargs):
	self.__kiduxPluginDebug("menuFileSend")
        receiver = args[0].parentConversationWindow.conversation.switchboard.firstUser
        if self.isFileTransferAllowed(receiver):
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)
        else :
            self.dialogs.fileTransferPreventDialog(receiver)

    def logOutgoingMessage(self, *args, **kwargs):
        self.__kiduxPluginDebug("logOutgoingMessage")
	contacts = args[1].switchboard.members.keys()
        message = args[2]
        receiver = args[1].switchboard.firstUser
        #sender = self.accountUser
        receiverIP = args[1].switchboard.host
        senderIP = self.personalIP
        allowed = self.isContactAllowed(receiver)
        if allowed:
            tag = ""
        else:
            tag = "[Blocked Conversation] "
	conversationId = args[1].switchboard.authenticationString
	print "logOutgoingMessage" , "conversationId: " , conversationId
	if not conversationId in self.switchboardList:
	    self.parentalController.startConversation(self.accountUser, conversationId, contacts)
	    self.switchboardList.append(conversationId)
	self.parentalController.logConversation(self.accountUser, conversationId, None, message)
        if allowed:
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)

    def logIncomingMessage(self, *args, **kwargs):
        self.__kiduxPluginDebug("logIncomingMessage")
	contacts = args[1].switchboard.members.keys()
        message = args[4]
        sender = args[2]
        senderIP = args[1].switchboard.host
        receiver = self.accountUser
        receiverIP = self.personalIP
        #TODO: tratando menssagens em chat, REFAZER COM WRAP
        allowed = self.isContactAllowed(sender)
        if allowed:
            tag = ""
        else:
            tag = "[Blocked Conversation] "
	conversationId = args[1].switchboard.authenticationString
	print "logIncomingMessage" , "conversationId: " , conversationId
	if not conversationId in self.switchboardList:
	    self.parentalController.startConversation(self.accountUser, conversationId, contacts)
	    self.switchboardList.append(conversationId)
	self.parentalController.logConversation(self.accountUser, conversationId, sender, message)
        if allowed:
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)

    def preventEmail(self,  *args,  **kwargs):
        self.__kiduxPluginDebug("preventEmail")
        receiver = args[0].user._email
        if self.isFileTransferAllowed(receiver):
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)
        else :
            self.dialogs.emailPreventDialog(receiver)

    def preventInvite(self,  *args,  **kwargs):
        self.__kiduxPluginDebug("preventInvite")
        contactId = args[1]
        if self.isContactAllowed(contactId):
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)
        else :
            self.dialogs.showConversationBlockedDialog(contact)

    def checkAccountBlockedAndCreate(self, accountId, buddies, dictGroup):
        self.__kiduxPluginDebug("checkAccountBlockedAndCreate")
        blocked, exists = self.isAccountAllowed(accountId)
        if blocked:
            self.controller.logout()
        else:
            if not exists:
                #TODO: Verificar o funcionamento do novo NewAccount
                #dictGroupByBuddies = self.getEntireBuddyListDict(buddies, dictGroup)
                #self.parentalController.newAccount(accountId, dictGroupByBuddies)
                self.parentalController.newAccount(accountId, self.buddyList)
            else:
                pass

    def preventUnloadPlugin(self,  *args,  **kwargs):
        self.__kiduxPluginDebug("preventUnloadPlugin")
        plugin = args[1]
        self.kiduxPluginDebug(plugin)
        #TODO: rever isto, plugin == plugin ???
        if plugin == plugin:
            pass
        else :
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)
            #self.dialogs.showConversationBlockedDialog(contact)

    def preventProfileView(self,*args,  **kwargs):
        self.__kiduxPluginDebug("preventProfileView")
        contactId = args[0].user._email
        if self.isContactAllowed(contactId):
            retval = yield aspects.proceed(*args,  **kwargs)
            yield aspects.return_stop(retval)

    #TODO: This is the true fuction, delete "_" caracter from the name and erase the "** New setConversation Function **"
    def setConversation(self, object):
        self.__kiduxPluginDebug("setConversation")
        if object.allowed == True:
            functor = UnblockContact(self.controller)
        else:
            functor = BlockContact(self.controller)
        functor(object.contactId)

    def _setConversation(self, object):
        self.__kiduxPluginDebug("_setConversation")
        print "[DEBUG]: setConversation PROCESSED"
        pass

    def isContactAllowed(self, contactId):
        return self.parentalController.isContactAllowed(contactId)

    def isAccountAllowed(self,  account):
        retObject = self.parentalController.isAccountAllowed(account)
        return retObject.accountBlocked,  retObject.accountExists

    def isFileTransferAllowed(self, contactId):
        return self.parentalController.isFileTransferAllowed(contactId)


